#ifndef CLICK_IGMPCLIENT_HH
#define CLICK_IGMPCLIENT_HH
#include <click/config.h>
#include <click/element.hh>
#include <click/timer.hh>
#include <click/bighashmap.hh>
#include "igmpstate.hh"


CLICK_DECLS


typedef uint8_t SocketPort;

/** \brief Is an IPAddress a multicast address? (Method is present in Click! v1.7)
 *
 */
bool is_multicast(const IPAddress&);


/** \brief IGMPClient class responsible for sending multicast packets to the correct sockets (see rfc3376 p. 3)
 *
 */
class IGMPClient: public Element{
	public:
		IGMPClient();
		virtual ~IGMPClient();
		const char *class_name() const	{ return "IGMPClient"; }
		const char *port_count() const	{ return "1/1-"; }
		const char *processing() const	{ return AGNOSTIC; }
		int configure(Vector<String>&, ErrorHandler*);
		Packet* pull(int);
		void push(int, Packet *);
		void add_handlers();
		///Implementation of IPMulticastListen described in rfc p. 3.
		int ipmulticastlisten(SocketPort*, const in_addr&, const IGMPFilterMode&, const Vector<in_addr>&);
		///Return client ip adress.
		in_addr getClientIP() const;
		void run_timer(Timer*);
		int initialize(ErrorHandler *);
	private:
		///Provides a write handler to join a group.
		static int join(const String &data, Element *element, void *thunk, ErrorHandler *errh);
		///Provides a write handler to leave a group.
		static int leave(const String &data, Element *element, void *thunk, ErrorHandler *errh);
		//Send a ReportMessage for 1 state
		void SendReportMessage(IGMPState*);
		//Packs states in grouprecords and then encapsulates them in a ReportMessage
		void SendReportMessage(const HashMap<uint32_t, IGMPState*>&);
		IPAddress clientip;
		HashMap<uint32_t, Vector<SocketPort*> > sockets;
		HashMap<uint32_t, IGMPState*> states;
		//Note: HashMap will become HashContainer (in Click 1.7) so look for HashContainer in Click! documentation
		Timer generalqtimer;
};

CLICK_ENDDECLS

#endif //CLICK_IGMPCLIENT_HH
